The globejs function plots surface maps and data points on a sphere that you can spin around and zoom. The function uses the http://threejs.org 3-d visualization library and is part of the threejs package for R, https://github.com/bwlewis/rthreejs. You can install the threejs package using the devtools package:

devtools::install_github("bwlewis/rthreejs")

This document illustrates making globes from images or from maps generated in R. The examples display in RStudio just like regular R plots and can be used in shiny applications or stand-alone web documents created with rmarkdown like this one. When viewing from a web browser we find that recent versions of Google’s chrome and Internet Explorer work very well.

Example 1: Using images as maps on the globe

Any image may be used as a surface map. For example, the globe on the right produced by the following R code uses a beautiful high-resolution NASA “blue marble” MODIS image downloaded from the web.

library("threejs")
earth <- "http://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73909/world.topo.bathy.200412.3x5400x2700.jpg"
globejs(img=earth, bg="white", emissive="#aaaacc")

You can plot points and bars over the globe by supplying data to the lat and long arguments, using the value and color arguments to control the height and color of each bar. Latitude and longitude values will only align properly with plate carrée equirectangular projection maps, also known as lat/long maps. Fortunately, lat/long map images are commonly available, and they’re also easy to create in R.

Generating maps in R

An impressive variety of sophisticated cartographic packages are available for R, and several of them can easily generate lat/long map images. See the spatial task view for a comprehensive list of available packages.

The maptools package by Roger Bivand and many contributors is a high-level plotting interface to the sp package that greatly simplifies plotting regional and global maps. Our examples illustrate making maps for display on the globe using the maptools package, but with minor modification the examples will work with other R packages like the excellent new rworldmap package.

Example 2: Bono awareness index

We start with fun map that approximates one published in the Onion’s atlas of the planet earth (thanks to Andy South for referencing this in his rworldmap package).

This example illustrates generating a basic map with political boundaries. The countries are colored according to a loose approximation of the Onion’s “Bono awareness index.” The example illustrates the required plot parameters to display a basic map like this on the globe.

A facsimile of the Bono awareness index color data may be found on my website at http://illposed.net/bono.rdata; the data are stored in a single-column R data frame whose row names are labeled with country names, a sample of which is shown here:

load(url("http://illposed.net/bono.rdata"))
bono[c(33,51,126,180,209),,drop=FALSE]
##                                                                          index
## Chile                Only thinks about nation when drawing up U2 tour schedule
## Ireland                Cares about welfare of nation nearly as much as his own
## Niger         Moved enough by nation's crisis to momentarily remove sunglasses
## South Africa           Cares about welfare of nation nearly as much as his own
## United States                             Frequently dedicates songs to nation

The index data are factors with five levels. We’ll use the factor levels to color the countries in our map. The trickiest part of preparing a map for display with globejs is setting up the plot parameters. The map needs to take up the entire plot region (no margins), and lat/long maps must have a 2:1 aspect ratio. Note that some of the map plotting functions available in R (including the maptools functions) override plot parameters. We illustrate that in the example below by showing the full set of required plot parameters, repeating the overridden ones in the maptools plot function. The complicated looking function that computes the map_palette colors simply darkens the default heat.color palette a bit.

library("maptools")
data(wrld_simpl)                             # Basic country shapes
load(url("http://illposed.net/bono.rdata"))  # Awareness index data

bgcolor <- "#000025"
earth <- tempfile(fileext=".jpg")
jpeg(earth, width=2048, height=1024, quality=100, bg=bgcolor, antialias="default")
par(mar = c(0,0,0,0),    pin = c(4,2),    pty = "m",    xaxs = "i",
    xaxt = "n",          xpd = FALSE,    yaxs = "i",    yaxt = "n")

map_palette <- apply(col2rgb(heat.colors(5)[5:1])/768,2,function(x)rgb(x[1],x[2],x[3]))
# Restrict bono data to countries from the maptools package
bono <- bono[rownames(bono) %in% wrld_simpl$NAME, ,drop=FALSE]
# Set a default color for each country and the colors from the bono data
clrs <- rep(map_palette[1], length(wrld_simpl$NAME))
names(clrs) <- wrld_simpl$NAME
clrs[rownames(bono)] <- map_palette[bono$index]

plot(wrld_simpl,  col=clrs,   bg=bgcolor,        border="cyan",  ann=FALSE,
     axes=FALSE,  xpd=FALSE,  xlim=c(-180,180), ylim=c(-90,90),  setParUsrBB=TRUE)

graphics.off()

legendcol=heat.colors(5)[5:1]
globejs(earth,  bg="white")

Use R jpeg or PNG antialiasing to produce smoother-looking border and boundary lines in your map image. Note that the image background must be the same as the plot background or antialiasing can result in image edge artifacts. Those artifacts become objectionably visible when the left and right edges are glued together on the globe.

WebGL viewers may also notice some polar distortion that dissipates as the plot is zoomed in (less noticeable in Canvas renderings). We’re working on improving that…

Example 3: Adding bars to make a spiky globe

Our motivation for this package was the well-known spiky globe visualization http://data-arts.appspot.com/globe/. We can use the globejs function to plot bars over the globe on arbitrary points with just a few lines of code.

The example also illustrates using a custom map generated by R, highlighting a country (Brazil), and adjusting the initial map rotation to bring the highlighted country to the front.

library("threejs")
library("maptools")
library("maps")
data(wrld_simpl, package="maptools")
data(world.cities, package="maps")
cities <- world.cities[order(world.cities$pop,decreasing=TRUE)[1:1000],]
value  <- 100 * cities$pop / max(cities$pop)


bgcolor <- "#000025"
earth <- tempfile(fileext=".jpg")
jpeg(earth, width=2048, height=1024, quality=100, bg=bgcolor, antialias="default")
par(mar = c(0,0,0,0), pin = c(4,2), pty = "m", xaxs = "i",
    xaxt = "n", xpd = FALSE, yaxs = "i", yaxt = "n")

col <- rep("black",length(wrld_simpl$NAME))    # Set a default country color
col[wrld_simpl$NAME=="Brazil"] <- "#003344"    # Highlight Brazil

plot(wrld_simpl, col=col,          bg=bgcolor, border="#111111", ann=FALSE,  axes=FALSE, 
     xpd=FALSE,  xlim=c(-180,180), ylim=c(-90,90),  setParUsrBB=TRUE)

graphics.off()

globejs(img=earth, bg="black", lat=cities$lat,     long=cities$long, value=value, 
        rotationlat=-0.34,     rotationlong=-0.38, fov=30)